﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SSharp.Core.Evaluator;
using SSharp.Core.DataTypes;

namespace SSharp.Core.Builtins.Macros {
	public class Cond : Macro {
		private static readonly Symbol ifSymbol = new Symbol("if");
		private static readonly Symbol elseSymbol = new Symbol("else");

		// a cond is an expression like
		// (cond (condition consequent)
		//       (condition consequent)
		//       ...)
		// with one special condition - else - which is always true.
		// to expand, simply go over the conditions and turn them into if expressions
		public object Expand(IList<object> args) {
			object result = null;
			// go over the clauses in reverse order, to build the if from inside out
			foreach (object obj in args.Reverse()) {
				IList<object> parts = List.Unpack(obj);
				if (parts == null || parts.Count != 2) {
					throw new SyntaxError("Cond: Expected a list of (condition expression). One item did not match: " + obj);
				}

				object condition = parts[0];
				object consequent = parts[1];

				if (elseSymbol.Equals(condition)) {
					if (result != null) {
						// there were clauses after the else
						throw new SyntaxError("Cond: Else must be last clause");
					}
					result = consequent;
				} else {
					// normal clause, i.e. not else
					if (result == null) {
						// for the last clause, no else branch.
						result = List.Create(
							ifSymbol,
							condition,
							consequent);
					} else {
						result = List.Create(
							ifSymbol,
							condition,
							consequent,
							result);
					}
				}
			}
			return result;
		}
	}
}
